package com.zhuzhe.blog.utils;

import org.apache.commons.lang3.time.DateUtils;
import org.quartz.CronExpression;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @需求描述:
 * @创建人:whh
 * @创建时间: 2020/4/15
 * @修改需求:
 * @修改人:
 * @修改时间:
 * @需求思路:
 */
public class DateTimeUtil {

    /**
     * 英文简写（默认）如：2010-12-01
     */
    public static String FORMAT_SHORT = "yyyy-MM-dd";
    /**
     * 英文全称 如：2010-12-01 23:15:06
     */
    public static String FORMAT_LONG = "yyyy-MM-dd HH:mm:ss";
    /**
     * 精确到毫秒的完整时间 如：yyyy-MM-dd HH:mm:ss.S
     */
    public static String FORMAT_FULL = "yyyy-MM-dd HH:mm:ss.S";
    /**
     * 中文简写 如：2010年12月01日
     */
    public static String FORMAT_SHORT_CN = "yyyy年MM月dd";
    /**
     * 中文全称 如：2010年12月01日 23时15分06秒
     */
    public static String FORMAT_LONG_CN = "yyyy年MM月dd日  HH时mm分ss秒";
    /**
     * 精确到毫秒的完整中文时间
     */
    public static String FORMAT_FULL_CN = "yyyy年MM月dd日  HH时mm分ss秒SSS毫秒";

    public static void main(String[] args) throws Exception {

        System.out.println(differentDaysByMillisecond(string2Date("2018-01-01 00:00:00"), new Date()));
        String CRON_EXPRESSION = "00 52 09 20 08 ?";
        System.out.println(CRON_EXPRESSION);
        List<String> lTime = new ArrayList<String>();
        lTime = parser(CRON_EXPRESSION);
        for (int i = 0; i < lTime.size(); i++) {
            System.out.println("时间：" + lTime.get(i));
        }

        System.out.println(data2String(DateUtils.addDays(new Date(), -30)));

        System.out.println(formatDateByPattern(new Date()));
        System.out.println(getCron(new Date()));
        System.out.println(formatDateByPattern(changeTime(new Date(), 80)));
        System.out.println(changeTime(new Date(), 800));

        System.out.println(getTimeString());
        System.out.println("返回日期年份:" + getYear(new Date()));
        System.out.println("返回月份：" + getMonth(new Date()));
        System.out.println("返回当天日份" + getDay(new Date()));
        System.out.println("返回当天小时" + getHour(new Date()));
        System.out.println("返回当天分" + getMinute(new Date()));
        System.out.println("返回当天秒" + getSecond(new Date()));
        System.out.println("返回当天毫秒" + getMillis(new Date()));

        System.out.println(makeTime(getYear(new Date()), getMonth(new Date()), getDay(new Date()), getHour(new Date()),
            getMinute(new Date()), getSecond(new Date())));

    }

    // "ss mm HH dd MM ? yyyy"
    private static final SimpleDateFormat sdf = new SimpleDateFormat("ss mm HH dd MM ? ");

    /**
     * String 转 Date
     *
     * @param str
     * @return java.util.Date
     * @throws @author
     *             whh
     * @date 2020/7/16 11:04
     */
    public static Date string2Date(String str) throws Exception {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.parse(str);
    }

    /**
     * 日期修改天数，减一
     *
     * @param str
     * @param count
     * @return java.lang.String
     * @throws @author
     *             whh
     * @date 2020/7/29 18:10
     */
    public static String changeDateByday(String str, Integer count) {

        Calendar calendar = Calendar.getInstance(); // 创建Calendar 的实例

        try {
            // string转换date
            Date date = string2DateDd(str);
            calendar.setTime(date);
            calendar.add(Calendar.DAY_OF_MONTH, count); // 当前时间减去一天，即一天前的时间
            // date转换string丢出
            Date time = calendar.getTime();
            return data2String(time);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 日期修改天数，减一
     *
     * @param date
     * @param count
     * @return java.lang.String
     * @throws @author
     *             whh
     * @date 2020/7/29 18:10
     */
    public static Date changeDateByday(Date date, Integer count) {

        Calendar calendar = Calendar.getInstance(); // 创建Calendar 的实例

        try {
            calendar.setTime(date);
            calendar.add(Calendar.DAY_OF_MONTH, count); // 当前时间减去一天，即一天前的时间
            // date转换string丢出
            Date time = calendar.getTime();
            return time;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * String 转 Date
     *
     * @param str
     * @return java.util.Date
     * @throws @author
     *             whh
     * @date 2020/7/16 11:04
     */
    public static Date string2DateDd(String str) throws Exception {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.parse(str);
    }

    /**
     * String 转 Date
     *
     * @param str
     * @return java.util.Date
     * @throws @author
     *             whh
     * @date 2020/7/16 11:04
     */
    public static Date formatDateDd(String str) throws Exception {

        DateFormat sdf = new SimpleDateFormat(FORMAT_LONG);
        return sdf.parse(str);
    }

    /**
     * Date转String
     *
     * @param date
     * @return java.lang.String
     * @throws @author
     *             whh
     * @date 2020/7/16 11:03
     */
    public static String data2String(Date date) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_LONG);
        return sdf.format(date);
    }

    /**
     * Date转String yyyy-MM-dd
     *
     * @param date
     * @return java.lang.String
     * @throws @author
     *             whh
     * @date 2020/7/16 11:03
     */
    public static String data2StringDd(Date date) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_SHORT);
        return sdf.format(date);
    }

    /***
     * 功能描述：日期转换cron表达式
     * 
     * @param date
     * @return
     */
    public static String formatDateByPattern(Date date) {
        String formatTimeStr = null;
        if (Objects.nonNull(date)) {
            formatTimeStr = sdf.format(date);
        }
        return formatTimeStr;
    }

    /***
     * convert Date to cron, eg "0 07 10 15 1 ?"
     * 
     * @param date
     *            : 时间点
     * @return
     */
    public static String getCron(Date date) {
        return formatDateByPattern(date);
    }

    // 时间递增，当前时间+递增时间
    public static Date changeTime(Date date, Integer ascendingTime) throws Exception {
        // System.out.println(date);

        // 新建一个日期格式化类的对象，该对象可以按照指定模板格式化字符串
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
        // 新建一个日期对象，日期的值来源于字符串，由f将这个字符串格式化成为日期
        // Date date1 =f.parse(date.toString());
        // 新建一个日历对象。注意：类Calendar是抽象的要使用getInstance()实例化，或者实例化其子类
        Calendar calen = Calendar.getInstance();
        // 日历对象默认的日期为当前日期，调用setTime设置该日历对象的日期为程序中指定的日期
        calen.setTime(date);
        // 将日历的"秒"增加time
        calen.add(Calendar.SECOND, ascendingTime);
        // 获取日历对象的时间，并赋给日期对象c
        Date c = calen.getTime();
        // 用f格式化c并输出
        return c;

    }

    /**
     * 根据传递参数生成时间
     *
     * @param year
     * @param month
     * @param date
     * @param hour
     * @param minute
     * @param second
     * @return java.util.Date
     * @throws @author
     *             whh
     * @date 2020/7/16 10:30
     */
    public static Date makeTime(Integer year, Integer month, Integer date, Integer hour, Integer minute, Integer second)
        throws Exception {
        // System.out.println(date);
        // 新建一个日历对象。注意：类Calendar是抽象的要使用getInstance()实例化，或者实例化其子类
        Calendar calen = Calendar.getInstance();
        // 日历对象默认的日期为当前日期，调用setTime设置该日历对象的日期为程序中指定的日期
        calen.setTime(new Date());
        // 将日历的"秒"增加time
        calen.set(year, month, date, hour, minute, second);
        // 获取日历对象的时间，并赋给日期对象c
        Date c = calen.getTime();
        // 用f格式化c并输出
        return c;

    }

    /**
     * cron转时间
     * 
     * @author whh
     * @param cron
     * @return java.util.Date
     * @exception @date
     *                2020/9/10 9:19
     */
    public static Date cronParserDate(String cron) throws Exception {
        List<String> parser = parser(cron);
        Date date = string2Date(parser.get(0));

        return date;
    }

    /**
     * cron转date
     *
     * @param cronExpression
     * @return java.util.List<java.lang.String>
     * @throws @author
     *             whh
     * @date 2020/8/20 9:09
     */
    public static List<String> parser(String cronExpression) {
        List<String> result = new ArrayList<String>();
        if (cronExpression == null || cronExpression.length() < 1) {
            return result;
        } else {
            CronExpression exp = null;
            Calendar calendar = Calendar.getInstance();
            String cronDate = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH) + 1) + "-"
                + calendar.get(Calendar.DATE);
            String sStart = cronDate + " 00:00:00";
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date dStart = null;
            Date dEnd = null;
            try {
                exp = new CronExpression(cronExpression);
                dStart = sdf.parse(sStart);
                calendar.setTime(dStart);
                calendar.add(Calendar.DATE, 1);
                dEnd = calendar.getTime();
            } catch (ParseException e) {
                e.printStackTrace();
                return result;
            }
            Date dd = new Date();
            dd = exp.getNextValidTimeAfter(dd);
            result.add(sdf.format(dd));
            dd = exp.getNextValidTimeAfter(dd);

            exp = null;
        }
        return result;
    }

    /**
     * 获取当前时间
     */
    public static String getTimeString() {
        SimpleDateFormat df = new SimpleDateFormat(FORMAT_LONG);
        Calendar calendar = Calendar.getInstance();
        return df.format(calendar.getTime());
    }

    /**
     * 获取日期年份
     *
     * @param date
     *            日期
     * @return
     */
    public static int getYear(Date date) {

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.YEAR);
    }

    /**
     * 功能描述：返回月
     *
     * @param date
     *            Date 日期
     * @return 返回月份
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH);
    }

    /**
     * 功能描述：返回日期
     *
     * @param date
     *            Date 日期
     * @return 返回日份
     */
    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 功能描述：返回小时
     *
     * @param date
     *            日期
     * @return 返回小时
     */
    public static int getHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 功能描述：返回分
     *
     * @param date
     *            日期
     * @return 返回分钟
     */
    public static int getMinute(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MINUTE);
    }

    /**
     * 返回秒钟
     *
     * @param date
     *            Date 日期
     * @return 返回秒钟
     */
    public static int getSecond(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.SECOND);
    }

    /**
     * 功能描述：返回毫
     *
     * @param date
     *            日期
     * @return 返回毫
     */
    public static long getMillis(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getTimeInMillis();
    }

    /**
     * 通过时间秒毫秒数判断两个时间的间隔（包含截至时间）
     * 
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDaysByMillisecond(Date date1, Date date2) {
        int days = (int)(NumericUtil.divide(date2.getTime() - date1.getTime(), (1000 * 3600 * 24)));
        return days + 1;
    }

}
